Tutoriel Gtk2Hs 1 - Introduction
Tutoriel Gtk2Hs 2 - Démarrage
Tutoriel Gtk2Hs 3.1 - Empaquetage des widgets
Tutoriel Gtk2Hs 3.2 - Programme de démonstration de l'empaquetage
Tutoriel Gtk2Hs 3.3 - Empaquetage en utilisant des grilles
Tutoriel Gtk2Hs 4.1 - Le widget bouton
Tutoriel Gtk2Hs 4.2 - Réglages, curseurs, plages de valeurs
Tutoriel Gtk2Hs 4.3 - Étiquettes
Tutoriel Gtk2Hs 4.4 - Flèches et infobulles
Tutoriel Gtk2Hs 4.5 - Dialogues, Stock Items et barres de progression
Tutoriel Gtk2Hs 4.6 - Zone de saisie de texte et barres d'état
Tutoriel Gtk2Hs 4.7 - Boutons compteurs
Tutoriel Gtk2Hs 5.1 - Calendrier
Tutoriel Gtk2Hs 5.2 - Sélection de fichiers
Tutoriel Gtk2Hs 5.3 - Sélection de fontes et de couleurs
Tutoriel Gtk2Hs 5.4 - Bloc-notes
Tutoriel Gtk2Hs 6.1 - Fenêtres avec défilement
Tutoriel Gtk2Hs 6.2 - Boites d’événements et boites à boutons
Tutoriel Gtk2Hs 6.3 - Le conteneur de disposition
Tutoriel Gtk2Hs 6.4 - Fenêtres à volets et cadres d'apparences
Tutoriel Gtk2Hs 7.1 - Menus et barres d'outils
Tutoriel Gtk2Hs 7.2 - Menus contextuels, actions radios et bascules
Jusqu’à maintenant, nous avons empaqueté des widgets soit avec des boites verticales et horizontales, soit avec des tableaux. Vous pouvez, aussi positionner des widgets dans toutes les positions que vous voulez en utilisant un widget Fixed ou Layout. L'utilisation du widget Fixed n'est pas recommandé car il ne se redimensionne pas très bien.
Le conteneur disposition est similaire au conteneur fixé,à la différence qu'il implémente une zone de défilement infinie (en réalité limitée à 2^32).
Un widget disposition se crée avec:
layoutNew :: Maybe Adjustment -> Maybe Adjustment -> IO Layout
Comme vous pouvez le voir, on peut spécifier optionnellement les objets d'ajustement que le conteneur de disposition utilisera pour le défilement.
Vous pouvez ajouter et déplacer des widgets dans le conteneur disposition en utilisant les fonctions suivantes:
layoutPut :: (LayoutClass self, WidgetClass childWidget)=> self -> childWidget -> Int -> Int -> IO ()
layoutMove :: (LayoutClass self, WidgetClass childWidget)=> self -> childWidget -> Int -> Int -> IO ()
Le premier paramètre est la position en x, le deuxième la position en y. Le côté en haut à gauche est à (0,0), x augmente de gauche à droite et y de haut en bas.
La taille du conteneur Layout peut être définie en utilisant la fonction:
layoutSetSize :: LayoutClass self => self -> Int -> Int -> IO ()
Le premier paramètre est la largeur de la totalité de la zone pouvant défiler, le second, la hauteur.
Dans l'exemple, on place une liste d'étiquettes, chacune avec une lettre majuscule dans un cercle autour d'un centre. Les étiquettes sont positionnées perpendiculairement au rayon au moyen de la fonction :
labelSetAngle :: labelClass self => self -> Double -> IO ()
L'angle est en degrés, pris dans le sens trigonométrique (anti-horaire).
Le widget disposition est placé dans une fenêtre avec défilement au moyen de containerAdd car elle n'a pas besoin de view port (comme vu dans le chapitre 6.1). Les étiquettes sont positionnées en utilisant les coordonnées angulaires qui sont converties en coordonnées cartésiennes avec les fonctions sin et cos. Celles-ci prennent des radians comme arguments (entre 0 et 2*pi). Dans l'exemple, la largeur et la hauteur sont paramétrables, comme l'est la liste à afficher. De plus, dans la fonction main, les coins de Layout sont marqués, de sorte que vous puissiez facilement modifier sa taille si vous le souhaitez.
import Graphics.UI.Gtk
main :: IO ()
main = do
initGUI
window <- windowNew
set window [windowTitle := "Alphabet" , windowDefaultWidth := 350,
windowDefaultHeight := 350 , containerBorderWidth := 10]
sw <- scrolledWindowNew Nothing Nothing
set sw [scrolledWindowPlacement := CornerBottomRight,
scrolledWindowShadowType := ShadowEtchedIn,
scrolledWindowHscrollbarPolicy := PolicyAutomatic,
scrolledWindowVscrollbarPolicy := PolicyAutomatic ]
containerAdd window sw
layt <- layoutNew Nothing Nothing
layoutSetSize layt myLayoutWidth myLayoutHeight
widgetModifyBg layt StateNormal (Color 65535 65535 65535)
containerAdd sw layt
upleft <- labelNew (Just "+(0,0)")
layoutPut layt upleft 0 0
upright <- labelNew (Just ("+(" ++ (show (myLayoutWidth - 50)) ++",0)"))
layoutPut layt upright (myLayoutWidth -50) 0
dwnright <- labelNew (Just ("+(0," ++ (show (myLayoutHeight -20)) ++ ")"))
layoutPut layt dwnright 0 (myLayoutHeight -20)
dwnleft <- labelNew (Just ("+(" ++ (show(myLayoutWidth -70)) ++ "," ++
(show (myLayoutHeight -20)) ++ ")"))
layoutPut layt dwnleft (myLayoutWidth -70) (myLayoutHeight - 20)
labels <- sequence $ map (labelNew . Just) txtls
sequence_ $ map (\x -> widgetModifyFg x StateNormal (Color 0 0 45000)) labels
let wnums = zip labels [0..]
sequence_ $ map (myLayoutPut layt) wnums
widgetShowAll window
onDestroy window mainQuit
mainGUI
-- parameters
myLayoutWidth :: Int
myLayoutWidth = 800
myLayoutHeight :: Int
myLayoutHeight = 800
txtls :: [String]
txtls = map (\x -> x:[]) ['A'..'Z']
-- end parameters
step :: Double
step = (2 * pi)/(fromIntegral (length txtls))
ox :: Int
ox = myLayoutWidth `div` 2
oy :: Int
oy = myLayoutHeight `div` 2
radius :: Double
radius = 0.25 * (fromIntegral ox)
angle :: Int -> Double
angle num = 1.5 * pi + (fromIntegral num) * step
num2x :: Int -> Int
num2x n = ox + relx where
relx = round $ radius * (cos (angle n))
num2y :: Int -> Int
num2y n = oy + rely where
rely = round $ radius * (sin (angle n))
myLayoutPut :: Layout -> (Label, Int) -> IO ()
myLayoutPut lt (lb, n) = do
layoutPut lt lb (num2x n) (num2y n)
labelSetAngle lb (letterAngle n)
letterAngle :: Int -> Double
letterAngle n = (270 - degree) where
degree = (angle n) * (180.0 /pi)